package org.artifact.core.plugin.netty.codec;

import java.util.List;

import org.artifact.core.context.bytebuf.IByteBuff;
import org.artifact.core.context.bytebuf.NettyByteBuf;
import org.artifact.core.context.packet.IPacket;
import org.artifact.core.context.session.ISession;
import org.artifact.core.lang.IServer;
import org.artifact.core.plugin.netty.handler.NettyHandler;
import org.artifact.core.plugin.netty.packet.NettyPacketUtil;
import org.artifact.core.plugin.netty.session.NettySessionAttrEnum;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.Attribute;

public class NettyDecoder extends ByteToMessageDecoder {

	static final Log log = LogFactory.get(NettyDecoder.class);

	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
		int readLength = in.readableBytes();
		if (readLength < Integer.BYTES) {
			return;
		}
		// 记录即将开始读取的位置
		in.markReaderIndex();

		int totalLength = in.readInt();

		// 没有内容
		if (totalLength <= 0) {
			ctx.close();
			return;
		}

		// 不够包长，不进行接收
		if (readLength < totalLength + Integer.BYTES) {
			in.resetReaderIndex();
			return;
		}

		// 解密
		NettyPacketUtil.decrypt(in, getDecryptionKeys(ctx), 0, readLength);
		
		// 计算校验和
		short sumCheck = NettyPacketUtil.sumCheck(in, Short.BYTES, readLength - Short.BYTES);
		
		short sumCheck2 = in.readShort();
		if (sumCheck != sumCheck2) {
			log.info("非法包-校验和不一致");
			ctx.close();
			return;
		}

		IByteBuff byteBuff = new NettyByteBuf(in);
		
		IPacket packet = IServer.me().getContext().getPacketFactory().create();
		packet.forByteBuff(byteBuff);
		out.add(packet);
	}

	private int[] getDecryptionKeys(ChannelHandlerContext ctx) {
		Channel channel = ctx.channel();
		Attribute<ISession> attach = channel.attr(NettyHandler.SESSION);
		ISession session = null;
		if ((session = attach.get()) == null) {
			// 解密密钥
			Attribute<int[]> decryptionKeysAttribute = channel.attr(NettyHandler.DECRYPTION_KEYS_ATTRIBUTE_KEY);
			int[] decryptionKeys = null;
			if ((decryptionKeys = decryptionKeysAttribute.get()) == null) {
				// 设置默认解密密钥
				decryptionKeys = NettyPacketUtil.getDefaultCustomDecryptionKeys();
				decryptionKeysAttribute.set(decryptionKeys);
			}
			return decryptionKeys;
		}
		return session.getAttr(NettySessionAttrEnum.DECRYPT_KEY_SECRET);
	}
}
